import extraProps from '../configs/extra'
import { getFileName, isArray, isString } from 'node-aux'
import { readdir, readdirSync, readJson } from 'fs-extra'

import { createRequire } from 'node:module'
import { dirname, join, sep } from 'node:path'
import type { Plugin } from 'rollup'
import {
    CommandLineConfigure,
    RollifyConfigure,
    RollupConfigure,
    RollupConfigureItemProps
} from '../typing'
const require = createRequire(import.meta.url)
export const getLoader = function <T = any>(name: string): (options?: T) => Plugin<T> {
    if (!name || typeof name !== 'string') {
        throw new Error('加载的库不存在')
    }
    try {
        return require(name)
    } catch {
        throw new Error('加载的库不存在')
    }
}
export const useConfigList = <T extends RollupConfigure, C extends CommandLineConfigure>(
    configs: any[],
    userConfig: T,
    userParams: C
): RollupConfigure => {
    if (Array.isArray(configs) && configs.length) {
        const config: any = {}
        configs.forEach((configFun) => {
            if (typeof configFun !== 'function') {
                return
            }
            const itemConfig = configFun(userConfig, userParams)
            if (!itemConfig) {
                return
            }
            const key = itemConfig.name as RollupConfigureItemProps
            config[key] =
                typeof itemConfig.configure === 'function'
                    ? itemConfig.configure(config)
                    : itemConfig.configure
        })
        return config as RollupConfigure
    }
    return {}
}
export const transformCssModuleName = function (prefix: string, exclude?: string[]) {
    return (localName: string, file: string, _css: string): string => {
        if (!_css) {
            return `${prefix}-${localName}`
        }
        const [, fileName] = getDirAndName(file, exclude || ['src', 'index'])
        if (localName.slice(0, fileName.length) === fileName) {
            return `${prefix}-${localName}`
        }
        return `${prefix}-${fileName}-${localName}`
    }
}

export const getDirAndName = function (file: string, exclude: string[]) {
    if (!file) {
        return ['', '']
    }
    const dirs = dirname(file).split(sep)
    let dirName = ''
    const fileName = getFileName(file)
    while (dirs.length) {
        const name = dirs.pop()
        if (!name) {
            break
        }
        if (!exclude.includes(name)) {
            dirName = name || ''
            break
        }
    }
    return [dirName, fileName === 'index' ? dirName : fileName]
}
export const getExtraProps = function (userConfig: RollifyConfigure) {
    if (isArray(extraProps)) {
        const config = {}
        extraProps.forEach((key) => {
            const val = userConfig[key]
            if (val) {
                config[key] = val
            }
        })
        return config
    }
    return {}
}

export const omitIndex = function (entries: string) {
    if (isString(entries)) {
        return (chunInfo: any) => {
            const { name } = chunInfo
            if (name === 'index') {
                return entries.replace(/\/index/, '')
            }
            return entries
        }
    }

    return entries
}
export const getSubdirectories = async function (
    dirPath: string = process.cwd(),
    absolute: boolean = false
): Promise<string[]> {
    try {
        // 读取目录所有条目并获取类型信息
        const entries = await readdir(dirPath, { withFileTypes: true })

        // 筛选出目录类型并处理路径
        return entries
            .filter((entry) => entry.isDirectory())
            .map((entry) => {
                const dirName = entry.name
                // 根据需求返回相对路径或绝对路径
                return absolute ? join(dirPath, dirName) : dirName
            })
    } catch (error) {
        throw new Error('获取子目录失败:' + error)
    }
}
export const getSubdirectoriesSync = function (
    dirPath: string = process.cwd(),
    absolute: boolean = false
): string[] {
    try {
        // 同步读取目录所有条目并获取类型信息
        const entries = readdirSync(dirPath, { withFileTypes: true })
        // 筛选出目录类型并处理路径
        return entries
            .filter((entry) => entry.isDirectory())
            .map((entry) => {
                const dirName = entry.name
                // 根据需求返回相对路径或绝对路径
                return absolute ? join(dirPath, dirName) : dirName
            })
    } catch (error) {
        throw new Error('获取子目录失败:' + error)
    }
}
export interface PackageJsonType {
    name: string
    version: string
    description: string
    main: string
    scripts?: {
        test?: string
        build?: string
    }
    author: string | { name: string; email?: string; url?: string }
    license: string
    [key: string]: any
}
export async function getPackageJson(): Promise<PackageJsonType> {
    const packagePath = join(process.cwd(), 'package.json')

    try {
        return await readJson(packagePath)
    } catch (err) {
        throw new Error('无法获取项目配置')
    }
}
